package com.lijinjiang.view;

import com.lijinjiang.controller.PropertiesHandler;
import com.lijinjiang.controller.impl.PropertiesHandlerImpl;
import com.lijinjiang.exception.ConnectException;
import com.lijinjiang.exception.QueryException;
import com.lijinjiang.model.GlobalContext;
import com.lijinjiang.model.QueryData;
import com.lijinjiang.model.tree.Database;
import com.lijinjiang.model.tree.ServerConnection;
import com.lijinjiang.util.ImageUtil;

import javax.swing.*;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;
import java.awt.*;
import java.awt.event.*;
import java.sql.SQLException;
import java.util.Collection;
import java.util.List;
import java.util.Map;

/**
 * @ClassName QueryPane
 * @Description 新建查询页面
 * @Author Li
 * @Date 2022/8/26 13:43
 * @ModifyDate 2022/8/26 13:43
 * @Version 1.0
 */
public class QueryPanel extends JPanel {
    private PropertiesHandler propertiesHandler; // 全局环境

    private MainFrame mainFrame;

    private ServerConnection sc; // 服务器连接

    private Database db; // 数据库

    private JToolBar toolBar; // 数据库查询工具栏

    private JComboBox<ServerConnection> scBox; // 服务器连接的下拉选

    private JComboBox<Database> dbBox; // 数据库连接的下拉选

    private MyTextArea queryArea; // 写查询语句的面板

    private JTabbedPane resultPane; // 结果面板

    private JTextArea infoArea; // 信息面板

    public QueryPanel(MainFrame mainFrame, Database database) {
        this.setLayout(new BorderLayout());
        this.mainFrame = mainFrame;
        this.initComboBox(database); // 初始化下拉列表
        this.setBorder(null); // 不设置边框
        this.createQueryPane(); // 创建查询面板
        this.createToolBar(); // 创建工具栏
    }

    private void initComboBox(Database database) {
        propertiesHandler = new PropertiesHandlerImpl();
        this.scBox = new JComboBox<>(); // 初始化服务器连接节点的下拉选
        scBox.setPreferredSize(new Dimension(180, 30));
        this.dbBox = new JComboBox<>(); // 初始化数据库连接节点的下拉选
        dbBox.setPreferredSize(new Dimension(200, 30));

        scBox.setRenderer(new ListComboBoxCellRender()); // 设置渲染类
        // 将所有服务器连接添加至下拉列表
        List<ServerConnection> scs = propertiesHandler.getAllSC();
        for (ServerConnection scItem : scs) {
            scBox.addItem(scItem);
            if (scItem.getName().equalsIgnoreCase(database.getSc().getName())) {
                scBox.setSelectedItem(scItem);
                scItem.connect();
                this.sc = scItem;
            }
        }

        dbBox.setRenderer(new ListComboBoxCellRender()); // 设置渲染类


        // 刷新数据库下拉列表
        refreshDbBox(database);

        // 服务器连接下拉监听
        scBox.addItemListener(new ItemListener() {
            @Override
            public void itemStateChanged(ItemEvent e) {
                // 改变前的状态
                if (e.getStateChange() == ItemEvent.DESELECTED) {
                    // System.out.println("切换前：" + e.getItem());
                    QueryPanel.this.sc.setConnection(null);
                    QueryPanel.this.dbBox.removeAllItems();
                    QueryPanel.this.db = null;
                } else if (e.getStateChange() == ItemEvent.SELECTED) {
                    ServerConnection serverConnection = (ServerConnection) QueryPanel.this.scBox.getSelectedItem();
                    QueryPanel.this.sc = serverConnection;
                    try {
                        serverConnection.connect();
                    } catch (ConnectException ce) {
                        JOptionPane.showMessageDialog(mainFrame, ce.getMessage(), "错误", JOptionPane.ERROR_MESSAGE);
                        return;
                    }
                }
            }
        });

        dbBox.addPopupMenuListener(new PopupMenuListener() {
            @Override
            public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
                refreshDbBox(database);
            }

            @Override
            public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {

            }

            @Override
            public void popupMenuCanceled(PopupMenuEvent e) {

            }
        });

        // 数据库下拉框添加监听
        dbBox.addItemListener(new ItemListener() {
            @Override
            public void itemStateChanged(ItemEvent e) {
                // 改变前的状态
                if (e.getStateChange() == ItemEvent.DESELECTED) {
                    // System.out.println("切换前：" + e.getItem());
                    QueryPanel.this.db.setConnection(null);
                } else if (e.getStateChange() == ItemEvent.SELECTED) {
                    //System.out.println("切换后：" + e.getItem());
                    Database selectedDb = (Database) QueryPanel.this.dbBox.getSelectedItem();
                    QueryPanel.this.db = selectedDb;
                    selectedDb.connect();
                }
            }
        });

    }

    private void refreshDbBox(Database database) {
        if (this.sc != null && this.dbBox.getItemCount() == 0) {
            List<Database> dbs = this.sc.getDatabases();
            for (Database dbItem : dbs) {
                dbBox.addItem(dbItem);
                if (dbItem.getDbName().equalsIgnoreCase(database.getDbName())) {
                    dbBox.setSelectedItem(dbItem);
                    dbItem.connect();
                    this.db = dbItem;
                }
            }
        }
    }

    // 创建查询面板
    private void createQueryPane() {
        JScrollPane topPane = new JScrollPane();

        // 上方的写查询语句的文本域
        this.queryArea = new MyTextArea();
        topPane.setViewportView(queryArea);
        queryArea.setBorder(null); // 无边框
        topPane.setBorder(null); // 无边框

        // 下方的结果区域
        this.resultPane = new JTabbedPane();
        resultPane.setFocusable(false);
        JScrollPane infoPane = new JScrollPane();
        infoPane.setBorder(null); // 无边框
        this.infoArea = new JTextArea();
        infoArea.setBorder(null); // 无边框
        infoArea.setEditable(false);
        infoPane.setViewportView(infoArea);
        resultPane.addTab("信息", infoPane);

        JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, topPane, resultPane);
        splitPane.setDividerLocation(300); // 分隔符位置
        splitPane.setBorder(null); // 不设置边框
        this.add(splitPane, BorderLayout.CENTER);
    }

    // 创建工具栏
    private void createToolBar() {
        this.toolBar = new JToolBar(); // 工具栏

        // 运行操作
        JButton runBtn = new JButton("运行", ImageUtil.RUN_ICON);
        runBtn.setFocusable(false); // 不显示虚线框
        runBtn.addActionListener(e -> {
            if (this.db == null) {
                JOptionPane.showMessageDialog(mainFrame, "未指定数据库", "错误", JOptionPane.ERROR_MESSAGE);
                return;
            } else {
                this.infoArea.setText(""); // 清空信息面板
                removeResultPaneTab(); // 清空选项卡
                String text = queryArea.getText();
                if (text != null && !"".equalsIgnoreCase(text)) {
                    String[] sqlArray = text.split(";");
                    int index = 1;
                    for (String sql : sqlArray) {
                        String lowerSql = sql.toLowerCase();
                        if (lowerSql.startsWith("insert") || lowerSql.startsWith("delete") || lowerSql.startsWith("update")) {
                            QueryData queryData = new QueryData(db, sql); // 直接执行 sql 语句就行
                            try {
                                long startTime = System.currentTimeMillis();
                                queryData.execute();
                                long endTime = System.currentTimeMillis();
                                long time = endTime - startTime;
                                appendInfo(sql, "OK", time);
                            } catch (QueryException qe) {
                                // 出现异常
                                appendInfo(sql, qe.getMessage(), 0);
                                resultPane.setSelectedIndex(0);
                                return;
                            }
                        } else if (lowerSql.startsWith("select")) {
                            try {
                                long startTime = System.currentTimeMillis();
                                DataTable dataTable = new DataTable(db, sql);
                                long endTime = System.currentTimeMillis();
                                long time = endTime - startTime;
                                appendInfo(sql, "OK", time);
                                resultPane.addTab("结果" + index, dataTable);
                                resultPane.setSelectedComponent(dataTable);
                                dataTable.setBorder(null);
                                index++;
                            } catch (QueryException qe) {
                                appendInfo(sql, qe.getMessage(), 0);
                                resultPane.setSelectedIndex(0);
                                return;
                            }
                        } else {
                            appendInfo(sql, "请确认 SQL 语句是否正确", 0);
                        }
                    }
                }
            }
        });

        // 保存操作
        JButton saveBtn = new JButton("保存", ImageUtil.SAVE_ICON);
        saveBtn.setFocusable(false); // 不显示虚线框

        toolBar.add(saveBtn);
        toolBar.add(scBox);
        toolBar.add(dbBox);
        toolBar.add(runBtn);

        toolBar.setFloatable(false); // 设置不可拖动
        toolBar.setLayout(new FlowLayout(FlowLayout.LEFT, 10, 0));
        this.add(toolBar, BorderLayout.NORTH);
    }

    // 移除所有的选项卡
    public void removeResultPaneTab() {
        int count = resultPane.getTabCount();
        if (count > 1) {
            for (int i = 1; i < count; i++) {
                resultPane.remove(i);
            }
        }
    }

    // 信息面板追加信息
    public void appendInfo(String sql, String message, long time) {
        infoArea.append(sql);
        infoArea.append(System.lineSeparator());
        infoArea.append("> " + message);
        infoArea.append(System.lineSeparator());
        infoArea.append("> " + "时间：" + time + " ms");
        infoArea.append(System.lineSeparator());
        infoArea.append(System.lineSeparator());
    }


}
